package router

import (
	"fmt"
	"github.com/apulis/bmod/file-server/configs"
	"github.com/apulis/bmod/file-server/internal/constant"
	"github.com/apulis/bmod/file-server/internal/handler/file"
	"github.com/gin-gonic/gin"
	tusd "github.com/tus/tusd/pkg/handler"
	"net/http"
	"path/filepath"
)

var (
	handler *tusd.UnroutedHandler
)

func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "*")
		c.Writer.Header().Set("Access-Control-Expose-Headers",
			"Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "*")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}

func RegisterRoutes(e *gin.Engine) {
	config := configs.Config
	e.Use(CORSMiddleware())
	g := e.Group(config.Prefix)

	switch config.StoreType {
	case "file":
		handler = file.NewHandler()
	}
	g.POST("", gin.WrapF(handler.PostFile))
	g.PATCH(":id", gin.WrapF(handler.PatchFile))
	g.HEAD(":id", gin.WrapF(handler.HeadFile))
	g.GET(":id", gin.WrapF(handler.GetFile))
	g.GET("/info/:id", info)
	g.DELETE(":id", gin.WrapF(handler.DelFile))
}

func info(c *gin.Context) {
	config := configs.Config

	id := c.Param("id")
	fileInfo, err := handler.InfoFile(id)

	if err != nil {
		constant.ErrorInfoFile.Message = err.Error()
		fail(c, constant.ErrorInfoFile)
		return
	}

	newPath := filepath.Join(fileInfo.MetaData["moduleName"], fileInfo.MetaData["filename"])
	respWithData(c, map[string]interface{}{
		"downloadLink": filepath.Join(config.Prefix, id),
		"storagePath":  fmt.Sprintf("%s/%s", config.FileStore.PvcRootPath, newPath),
		"dir":          newPath,
	})
}

func respWithData(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, gin.H{
		"code": constant.ActionSuccess.Code,
		"msg":  constant.ActionSuccess.Message,
		"data": data,
	})
}

func fail(c *gin.Context, err *constant.CodeMessage) {
	c.JSON(http.StatusInternalServerError, gin.H{
		"code": err.Code,
		"msg":  err.Message,
		"data": struct{}{},
	})
}
